function varargout = TLLogicaloperatorDlg(action,varargin)

% TL_LOGICALOPERATOR_DLG manages the user interface for TargetLink Logical Operator block
%
% SYNTAX dlgInfo = TLLogicaloperatorDlg('GetDlgInfo');
%   gets dialog info of TargetLink Logical Operator block
%
%   INPUT ARGUMENTS
%   -/-      
%
%   OUTPUT ARGUMENTS
%   dlgInfo     dialog information contains pageNames etc.
%
% SYNTAX [sheetDims, ctrlPos] = TLLogicaloperatorDlg('CtrlPositions', pageName, commonGeom, dlgInfo, sheetDims);
%   calculates the control positions of all controls of dialog page: <pageName>
%
%   INPUT ARGUMENTS
%   pageName        name of current page
%   commonGeom      common geometry data
%   dlgInfo         dialog information contains pageNames etc.
%   sheetDims       dimension of sheet
%
%   OUTPUT ARGUMENTS
%   sheetDims       modified dimension of sheet
%   ctrlPos         positions of controls
%
% SYNTAX dlgdata = TLLogicaloperatorDlg('Create', pageName, dlgfig, dlgdata);
%   creates all controls of dialog page: <pageName>
%
%   INPUT ARGUMENTS
%   pageName        name of current page
%   dlgfig          figure handle
%   dlgdata         dialog data
%
%   OUTPUT ARGUMENTS
%   dlgdata         modified dialog data
%
% SYNTAX [dlgdata,bModified] = TLLogicaloperatorDlg('Manage', pageName, dlgfig, dlgdata, pageAction);
%   manages all actions of dialog page: <pageName>
%
%   INPUT ARGUMENTS
%   pageName        name of current page
%   dlgfig          figure handle
%   dlgdata         dialog data
%   pageAction      modified control of current page
%
%   OUTPUT ARGUMENTS
%   dlgdata         modified dialog data
%   bModified       flag = 1, if dialog data are modified, =0 otherwise
%
% SYNTAX dlgdata = TLLogicaloperatorDlg('Update', dlgfig, dlgdata, pageNum);
%   updates all controls of dialog page: <pageNum>
%
%   INPUT ARGUMENTS
%   dlgfig          figure handle
%   dlgdata         dialog data
%   pageNum         number of current page
%
%   OUTPUT ARGUMENTS
%   dlgdata         modified dialog data
%
% SYNTAX TLLogicaloperatorDlg('Apply', dlgfig, dlgdata);
%   writes current blockdata to block and DD
%
%   INPUT ARGUMENTS
%   dlgfig      handle for dialog figure
%   dlgdata     dialog data
%
%   OUTPUT ARGUMENTS
%   - / -


% Author(s): D. Andoleit, T. Pietzsch
% $RCSfile: TLLogicaloperatorDlg.m $
% $ProjectName: e:/ARC/Components/HostSW/SimulinkBlocksets/TLBlocksets/CommonBlockset/CommonBlockset_SimBlocksUI/Sources/MSrc/project.pj $
% $Revision: 1.14 $
% $Date: 2011/07/21 13:33:38MESZ $
%
% Copyright ?2011 dSPACE GmbH. All rights reserved.


switch action

    case 'GetDlgInfo'
        hBlock = varargin{1};
        dlgInfo = tl_get_dlginfodefaults('tlsim');
        titleName = 'Logical Operator';
        pathinfo = tl_pathinfo(hBlock);
        dlgInfo.title = sprintf('TargetLink %s: %s', titleName, pathinfo.shortDisplayName);
        dlgInfo.pageNames   = {
            'Output & Logging'; ...
            'Documentation'};
        varargout{1} = dlgInfo;
        varargout{2} = get_tlcg_data(hBlock);

    case 'CtrlPositions'
        pageName     = varargin{1};
        commonGeom   = varargin{2};
        sheetDims    = varargin{4};
        switch pageName
            case 'Output & Logging'
                [sheetDims,ctrlPos] = ...
                    FcnCalcOutputControlPositions(commonGeom);

            case 'Documentation'
                bTblBlock = 0;
                bCodeComment = 1;
                [sheetDims,ctrlPos] = TLManageDocCtrls( ...
                    'ctrlpos', commonGeom, sheetDims, bCodeComment, bTblBlock);
        end
        varargout{1} = sheetDims;
        varargout{2} = ctrlPos;

    case 'Create'
        pageName = varargin{1};
        dlgfig   = varargin{2};
        dlgdata  = varargin{3};
        pageNum  = strmatch(pageName, dlgdata.pageNames, 'exact');

        switch pageName
            case 'Output & Logging'
                dlgdata = ...
                    FcnCreateOutputControls(pageNum, dlgfig, dlgdata);

            case 'Documentation'
                dlgdata = ...
                    TLManageDocCtrls('create',pageNum,dlgfig,dlgdata);
        end
        dlgdata.pageData{pageNum}.ctrlPos = [];
        varargout{1} = dlgdata;

    case 'Manage',
        pageName   = varargin{1};
        dlgfig     = varargin{2};
        dlgdata    = varargin{3};
        pageAction = varargin{4};
        pageNum    = strmatch(pageName,dlgdata.pageNames,'exact');
        switch pageName
            case 'Output & Logging'
                [dlgdata, bModified] = ...
                    FcnManageOutputControls(pageNum,dlgfig,dlgdata,pageAction);
                
            case 'Documentation'
                [dlgdata,bModified] = ...
                    TLManageDocCtrls('callback',pageNum,dlgfig,dlgdata,pageAction);
        end
        varargout{1} = dlgdata;
        varargout{2} = bModified;

    case 'ManageSystemIcons',
        dlgfig     = varargin{1};
        dlgdata    = varargin{2};
        pageAction = varargin{3};
        [dlgdata, bModified] = FcnManageSystemIcons(dlgfig,dlgdata,pageAction);
        varargout{1} = dlgdata;
        varargout{2} = bModified;

    case 'Update'
        dlgfig  = varargin{1};
        dlgdata = varargin{2};
        pageNum = varargin{3};
        pageName = dlgdata.pageNames{pageNum};
        switch pageName
            case 'Output & Logging'
                dlgdata = FcnUpdateOutputControls(dlgdata, dlgfig, pageNum);
                
            case 'Documentation'
                TLManageDocCtrls('update', pageNum, dlgfig, dlgdata);
        end
        varargout{1} = dlgdata;

    case 'Apply'
        dlgdata  = varargin{2};
        bClose   = varargin{3};
        [dlgdata, bClose] = tl_apply_blockdata(dlgdata, bClose);
        varargout{1} = dlgdata;
        varargout{2} = bClose;

    otherwise
        error(['Invalid action "' action '"']);
end


%-----------------------------------------------------------------------------------------
% FcnManageSystemIcons manage actions of toolbar icons
%
% INPUT ARGUMENTS
%   dlgfig      handle for dialog figure
%   dlgdata     dialog data
%   action      action at one control of current page
%
% OUTPUT ARGUMENTS
%   dlgdata     modified dialog data
%   bModified   flag = 1, if dialog data are modified, =0 otherwise
%-----------------------------------------------------------------------------------------
function [dlgdata, bModified] = FcnManageSystemIcons(dlgfig, dlgdata, action) %#ok

bModified = false;
switch action
    case 'EditCode'
        % look for associated production code file
        [codefile,blockstr] = get_codefile(dlgdata.model);
        if ~isempty(codefile)
            codeedit(codefile,blockstr);
        end

    case 'ViewCode'
        tl_create_links_to_model('ShowComputation',dlgdata.model, 'output');

    otherwise
        error('Invalid callback');

end % switch(action)


%-----------------------------------------------------------------------------------------
% FcnCalcOutputControlPositions calculates positions for all controls on output page
%
% INPUT ARGUMENTS
%   commonGeom      common geometrie information
%
% OUTPUT ARGUMENTS
%   sheetDims       modified dimension of sheet
%   ctrlPos         positions of controls
%
% HINT:
% Positions are calculated from the bottom left of the figure to avoid
% dependencies on figure size
%-----------------------------------------------------------------------------------------
function [sheetDims,ctrlPos] = FcnCalcOutputControlPositions(commonGeom)

% calculate positions of output controls
excludedCtrls = {'allscaling','inheritproperties', 'castoutput', 'width', 'element', 'scaling', 'scalarExp'};
[sheetDims, ctrlPosOutputFrame, colOutputFrame, colDelta, rowDelta] =  ...
    tl_calc_ctrls_positions(commonGeom, excludedCtrls); %#ok

% calculate positions of logging controls
excludedCtrls = {'autoscaling'};
[sheetDims, ctrlPos] = ...
    TLManageLoggingCtrls('calcCtrls', commonGeom, sheetDims, excludedCtrls);

% merge position structs
fieldNameList = fieldnames(ctrlPosOutputFrame);
fieldNameList = reshape(fieldNameList,1,length(fieldNameList));
for fieldName = fieldNameList,
    fieldValue = ctrlPosOutputFrame.(char(fieldName));
    ctrlPos.(char(fieldName)) = fieldValue - [0, commonGeom.editHeight+rowDelta, 0 , 0];
end

% recalulate position for base type info
cx = ctrlPos.addressLabel(1);
cy = ctrlPos.typeLabel(2);
ctrlPos.baseTypeLabel = [cx,cy,ctrlPos.baseTypeLabel(3:4)];

% adapt box cordinates in consideration of missing base type controls
ctrlPos.tlcgoptGroupbox(4) = ctrlPos.tlcgoptGroupbox(4) ...
    - commonGeom.editHeight - rowDelta;
ctrlPos.tlcgoptGroupbox(2) = ctrlPos.logplotGroupbox(2) + ctrlPos.logplotGroupbox(4)...
    + commonGeom.textHeight;

ctrlPos.addoptGroupbox(2) = ctrlPos.tlcgoptGroupbox(2) + ctrlPos.tlcgoptGroupbox(4)...
    + commonGeom.textHeight;

% base type info field
cx = cx + ctrlPos.baseTypeLabel(3) + colDelta/3;
w = ctrlPos.tlcgoptGroupbox(3) - cx - colDelta/3;
ctrlPos.baseTypeInfo = [cx, cy, w, ctrlPos.baseTypeInfo(4)];

strings_and_styles = {...
    'Operator:',         'text'; ...
    'Number of inputs:', 'text'; ...
    '123',               'edit'; ...
    '+',                 'pushbutton'};

[operatorLabelSize, ...
    ninpLabelSize, ...
    ninpEditSize, ...
    ninpButtonSize] = ...
    ds_get_uicontrol_sizes(commonGeom,strings_and_styles);

% finetune some results
ninpButtonSize = ninpButtonSize .* [1 0.5];

% define an additional box for operator etc.
ctrlPos.opGroupbox = ctrlPos.addoptGroupbox;

% all controls lie in one row
cy = commonGeom.frameBottomEdgeBuffer;

% operator Label
cx = colOutputFrame(1);
ctrlPos.operatorLabel = [cx cy operatorLabelSize];

% operator edit field
cx = colOutputFrame(2);
ctrlPos.operatorPopup = [cx cy ctrlPosOutputFrame.nameEdit(3) commonGeom.editHeight];

% number of inputs label
cx = cx + ctrlPos.operatorPopup(3) + colDelta;
ctrlPos.ninpLabel = [cx cy ninpLabelSize];

% number of inputs edit field
cx = cx + ninpLabelSize(1) + colDelta/3;
ctrlPos.ninpEdit = [cx cy ninpEditSize];

% up and down buttons
cx = cx + ninpEditSize(1) + 5;
ctrlPos.ninpupButton = ...
    [cx (cy + commonGeom.editHeight/2) ninpButtonSize];
ctrlPos.ninpdownButton = ...
    [cx cy ninpButtonSize];

% calculate sheet Dimensions
width = ctrlPos.tlcgoptGroupbox(3) ...
    + 2 * commonGeom.frameSideEdgeBuffer;
height = ctrlPos.logplotGroupbox(4) ...
    + ctrlPos.tlcgoptGroupbox(4) ...
    + ctrlPos.opGroupbox(4) ...
    + 3 * commonGeom.textHeight ...
    + commonGeom.sheetBottomEdgeBuffer;
    + commonGeom.sheetTopEdgeBuffer;
sheetDims = [width height];


%-----------------------------------------------------------------------------------------
% FcnCreateOutputControls creates the figure window
%
% INPUT ARGUMENTS
%   pageNum     number of current page
%   dlgfig      handle for dialog figure
%   dlgdata     dialog data
%
% OUTPUT ARGUMENTS
%   dlgdata     modified dialog data
%-----------------------------------------------------------------------------------------
function dlgdata = FcnCreateOutputControls(pageNum,dlgfig,dlgdata)

% create logging controls
dlgdata = TLManageLoggingCtrls('create', pageNum, dlgfig, dlgdata);

ctrlPos  = dlgdata.pageData{pageNum}.ctrlPos;
pageName = dlgdata.pageNames{pageNum};

% create standard variable controls
dlgdata = TLManageVariableCtrls('create', pageNum, dlgfig, dlgdata);
% no scaling controls

Children = dlgdata.pageData{pageNum}.children;

% modify panel title
set(dlgdata.pageData{pageNum}.children.tlcgoptGroupbox, 'Title', 'Output');

Children.opGroupbox = uipanel( ...
    'Parent',            dlgfig, ...
    'Title',            {'Operator and number of inputs'}, ...
    'Units',            'pixels', ...
    'Position',          ctrlPos.opGroupbox);

% operator controls
Children.operatorLabel = uicontrol( ...
    'Parent',             Children.opGroupbox, ...
    'Style',              'text', ...
    'String',             'Operator:', ...
    'Position',           ctrlPos.operatorLabel);

Children.operatorPopup = uicontrol( ...
    'Parent',             Children.opGroupbox, ...
    'BackgroundColor',    'w', ...
    'Style',              'popupmenu', ...
    'String',             {'AND'}, ... %operators, ...
    'Value',              1, ... %find(strcmp(operators,data.operator) == 1), ...
    'Position',           ctrlPos.operatorPopup, ...
    'Callback',           sprintf('tldlg(''%s'',gcbf,''operatorPopup'')',pageName));

% number of inputs controls
Children.ninpLabel = uicontrol( ...
    'Parent',             Children.opGroupbox, ...
    'Style',              'text', ...
    'String',             'Number of inputs:', ...
    'Position',           ctrlPos.ninpLabel);
userData = struct('min', 1, 'max', 2^31-1);
Children.ninpEdit = uicontrol( ...
    'Parent',             Children.opGroupbox, ...
    'BackgroundColor',    'w', ...
    'Style',              'edit', ...
    'Position',           ctrlPos.ninpEdit, ...
    'UserData',           userData, ...
    'Callback',           sprintf('tldlg(''%s'',gcbf,''ninpEdit'')',pageName));

Children.ninpupButton = uicontrol( ...
    'Parent',             Children.opGroupbox, ...
    'Style',              'pushbutton', ...
    'String',             '+', ...
    'Position',           ctrlPos.ninpupButton, ...
    'Callback',           sprintf('tldlg(''%s'',gcbf,''ninpupButton'')',pageName));

Children.ninpdownButton = uicontrol( ...
    'Parent',             Children.opGroupbox, ...
    'Style',              'pushbutton', ...
    'String',             '-', ...
    'Position',           ctrlPos.ninpdownButton, ...
    'Callback',           sprintf('tldlg(''%s'',gcbf,''ninpdownButton'')',pageName));

dlgdata.pageData{pageNum}.children = Children;


%-----------------------------------------------------------------------------------------
% FcnManageOutputControls manage control actions of output page
%
% INPUT ARGUMENTS
%   pageNum     number of current page
%   dlgfig      handle for dialog figure
%   dlgdata     dialog data
%   pageAction  action at one control of current page
%
% OUTPUT ARGUMENTS
%   dlgdata     modified dialog data
%   bModified   flag = 1, if dialog data are modified, =0 otherwise
%-----------------------------------------------------------------------------------------
function [dlgdata, bModified] = FcnManageOutputControls(pageNum,dlgfig,dlgdata,action)

Children = dlgdata.pageData{pageNum}.children;

switch action
    case 'operatorPopup'
        operators = get(Children.operatorPopup, 'String');
        dlgdata.data.operator = operators{get(Children.operatorPopup, 'Value')};
        if strcmpi(dlgdata.data.operator, 'NOT');
            % if "not" is selected, number of inputs is 1
            dlgdata.data.inputs = 1;
        end
        bModified = 1;

    case {'ninpEdit','ninpupButton','ninpdownButton'}
        [inputs, bModified] = tl_handle_editupdown( 'manage', ...
            dlgdata.data.inputs, ...
            [Children.ninpEdit Children.ninpupButton Children.ninpdownButton], ...
            Children.(action));
        inputsNum = str2num(inputs); %#ok<ST2NM>
        if bModified
            if ~isempty(inputsNum) && ~isequalwithequalnans(inputsNum, NaN)
                dlgdata.data.inputs = inputs;
            end
        end
        
    case {'logPopup', 'plotEdit', 'samplesEdit'}
        [dlgdata, bModified] = ...
            TLManageLoggingCtrls('manage', pageNum, dlgdata, action, 'logdata');

    otherwise %one of the variable controls
        [dlgdata, bModified] = ...
            TLManageVariableCtrls('manage', pageNum, dlgfig, dlgdata, action, 'output');

end


%-----------------------------------------------------------------------------------------
% FcnUpdateOutputControls updates output controls
%
% INPUT ARGUMENTS
%   dlgdata     dialog data
%   dlgfig      figure handle of dialog
%   pageNum     page Number
%
% OUTPUT ARGUMENTS
%   dlgdata     modified dialog data
%--------------------------------------------------------------------------
function dlgdata = FcnUpdateOutputControls(dlgdata,dlgfig,pageNum)

% update all variable controls
dlgdata =  TLManageLoggingCtrls('update',pageNum,dlgdata,'logdata','output');
dlgdata  = TLManageVariableCtrls('update', pageNum, dlgdata, 'output');
Children = dlgdata.pageData{pageNum}.children;

% update operator and number of inputs groupbox
% operator popup
operators = {'AND', 'OR', 'NAND', 'NOR', 'XOR', 'NOT'};
userData = get(Children.operatorPopup, 'UserData');
opValue = strmatch(dlgdata.data.operator, operators, 'exact');
userData.ctrlStatus.enable = 'on';
userData.ctrlStatus.value = opValue;
userData.ctrlStatus.string = operators;
set(Children.operatorPopup, 'UserData', userData);
% get new states for edit, up, and down controls
value = dlgdata.data.inputs;
states = tl_handle_editupdown('update', value, dlgdata, pageNum, 'ninpEdit');
if strcmpi(dlgdata.data.operator,'NOT')
   states.up   = 'off';
   states.down = 'off';
   states.edit = 'inactive';
end
userData = get(Children.ninpEdit, 'UserData');
userData.ctrlStatus = struct('enable', states.edit, 'string', dlgdata.data.inputs);
if ~states.isValid
    userData.ctrlStatus.iserror = true;
end
set(Children.ninpEdit, 'UserData', userData);
% up button
userData = get(Children.ninpupButton, 'UserData');
userData.ctrlStatus = struct('enable', states.up);
set(Children.ninpupButton, 'UserData', userData);
% down button
userData = get(Children.ninpdownButton, 'UserData');
userData.ctrlStatus = struct('enable', states.down);
set(Children.ninpdownButton, 'UserData', userData);

% write control status of extra controls to the control
ctrlsList = { ...
    'ninpEdit', ...
    'ninpupButton', ...
    'ninpdownButton', ...
    'operatorPopup'};

% set controls
TLManageLoggingCtrls('setCtrls',pageNum, dlgfig, dlgdata);
TLManageVariableCtrls('setCtrls', pageNum, dlgfig, dlgdata);
TLSetCtrlsStatus(dlgfig, Children, ctrlsList);
